const FFT = require('fft.js');

console.log('加载 EEGAttentionScore.js'); // 调试：确认模块加载

// 专注度固定长度队列类
class AttentionQueue {
    constructor(maxLength, clearLength) {
        if (clearLength >= maxLength) {
            throw new Error("清除长度必须小于最大长度");
        }
        this.maxLength = maxLength;
        this.clearLength = clearLength;
        this.queue = [];
    }

    enqueue(item) {
        if (this.queue.length >= this.maxLength) {
            this.queue.splice(0, this.clearLength); // 移除旧数据
        }
        this.queue.push(item); // 添加新数据
    }

    getQueue() {
        return [...this.queue]; // 返回队列副本，避免外部直接修改原数据
    }

    isFull() {
        return this.queue.length >= this.maxLength; // 判断队列是否已满
    }
}

// 专注度均值滤波器类
class AttentionMovingAverage {
    constructor(windowSize) {
        if (windowSize <= 0) {
            throw new Error("滤波窗口大小必须大于0");
        }
        this.windowSize = windowSize;
        this.window = [];
        this.sum = 0;
    }

    addSample(sample) {
        this.window.push(sample);
        this.sum += sample;

        if (this.window.length > this.windowSize) {
            this.sum -= this.window.shift(); // 移除最早的样本
        }

        return this.sum / this.window.length; // 返回当前窗口的平均值
    }
}

// 专注度得分服务类
class AttentionScoreMain {
    // 采样率（单位：Hz）
    Fs = 50;
    // 队列长度（6秒数据：250Hz * 6s = 1500点）
    queLen = this.Fs * 6;
    // 清除步长（2秒数据：250Hz * 2s = 500点）
    queStep = this.Fs * 2;
    // 滤波窗口大小（6个样本点）
    winSize = 6;
    // 延迟初始化的队列实例
    queue_data = null;
    // 初始化均值滤波器
    filter = new AttentionMovingAverage(this.winSize);

    // 使用箭头函数确保this指向正确
    initialize = () => {
        if (!this.queue_data) {
            // 创建队列实例，存储6秒的EEG数据
            this.queue_data = new AttentionQueue(this.queLen, this.queStep);
        }
    };

    /**
     * 计算功率谱密度（PSD）
     * @param {Array} eegData - 输入的EEG数据数组
     * @param {number} samplingRate - 采样率（Hz）
     * @returns {Object} 包含频率轴和PSD值的对象
     */
    computePSD(eegData, samplingRate) {
        const n = eegData.length;

        // 处理空数据情况
        if (n === 0) {
            console.warn("输入的EEG数据为空，无法计算PSD");
            return { frequencies: [], psd: [] };
        }

        let fftN = n;
        // 数据长度小于2时填充到2
        if (n <= 1) {
            fftN = 2;
        } else {
            // 计算大于等于n的最小2的幂
            const log2 = Math.ceil(Math.log2(n));
            fftN = Math.pow(2, log2);
        }

        // 生成填充后的数组（使用Float64Array提升数值精度）
        const paddedData = new Float64Array(fftN);
        eegData.forEach((val, idx) => {
            if (idx < fftN) paddedData[idx] = val || 0;
        });

        // 执行FFT计算
        const fft = new FFT(fftN);
        const fftInput = new Array(fftN * 2).fill(0);

        for (let i = 0; i < fftN; i++) {
            fftInput[i * 2] = paddedData[i]; // 实部
            fftInput[i * 2 + 1] = 0; // 虚部初始化为0
        }

        const fftOutput = fft.createComplexArray();
        fft.realTransform(fftOutput, fftInput);

        // 计算PSD和频率轴
        const psd = new Array(Math.floor(fftN / 2)).fill(0);
        const frequencies = new Array(Math.floor(fftN / 2)).fill(0);

        for (let i = 0; i < Math.floor(fftN / 2); i++) {
            const re = fftOutput[i * 2];
            const im = fftOutput[i * 2 + 1];
            const magnitude = Math.hypot(re, im); // 更高效的幅度计算方式
            psd[i] = (magnitude ** 2) / (fftN * samplingRate); // 计算PSD
            frequencies[i] = i * samplingRate / fftN; // 计算频率
        }

        return { frequencies, psd };
    }

    /**
     * 计算特定频段的功率
     * @param {Array} eegData - 输入的EEG数据数组
     * @param {number} samplingRate - 采样率（Hz）
     * @param {number} fLow - 频段下限（Hz）
     * @param {number} fHigh - 频段上限（Hz）
     * @returns {number} 频段内的功率总和
     */
    computePowerInBand(eegData, samplingRate, fLow, fHigh) {
        const { frequencies, psd } = this.computePSD(eegData, samplingRate);
        let power = 0;

        // 使用forEach优化循环性能
        frequencies.forEach((freq, index) => {
            if (freq >= fLow && freq <= fHigh && index < psd.length) {
                power += psd[index];
            }
        });

        return power;
    }

    /**
     * 计算专注度得分
     * @param {number} EEGFp1 - 单通道EEG数据点
     * @returns {number} 专注度得分（0-100，越高越专注）
     */
    calculateAttentionScore(EEGFp1) {
        this.initialize(); // 确保队列已初始化

        try {
            this.queue_data.enqueue(EEGFp1); // 入队新数据点

            if (this.queue_data.isFull()) { // 当队列满6秒数据时计算
                const eegData = this.queue_data.getQueue();
                if (eegData.length <= 1) {
                    console.warn("EEG数据长度不足，跳过处理");
                    return -1;
                }

                // 计算各频段功率（修正频段范围：Delta(0.5-4Hz), Theta(4-8Hz), Alpha(8-12Hz)）
                const deltaPower = this.computePowerInBand(eegData, this.Fs, 0.5, 4.0);
                const thetaPower = this.computePowerInBand(eegData, this.Fs, 4.0, 8.0);
                const alphaPower = this.computePowerInBand(eegData, this.Fs, 8.0, 12.0);

                const totalPower = deltaPower + thetaPower + alphaPower;
                if (totalPower === 0) return -1; // 避免除零错误

                // 计算专注度指标（Alpha波占比越高，专注度越高）
                const focusRatio = alphaPower / totalPower;
                // console.log(deltaPower)
                let attentionScore = focusRatio * 100;

                // 应用均值滤波并限制范围
                attentionScore = Math.round(this.filter.addSample(attentionScore));
                return Math.max(0, Math.min(100, attentionScore));

            }
        } catch (error) {
            console.error("计算专注度得分时出错:", error);
        }

        return -1; // 数据不足或计算失败时返回-1
    }
}

module.exports = { AttentionScoreMain };